#!/usr/bin/python
#
# Copyright 2010 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Settings dialog and related functions."""

__author__ = 'scott@forusers.com (Scott Kirkwood)'

import gettext
import gobject
import gtk
import logging
import os

from ConfigParser import SafeConfigParser

LOG = logging.getLogger('settings')

class SettingsDialog(gtk.Dialog):
    """Create a settings/preferences dialog for keyclick."""

    __gproperties__ = {}
    __gsignals__ = {
          'settings-changed' : (
            gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())
    }

    def __init__(self, unused_view, options):
        gtk.Dialog.__init__(self, title='Preferences', parent=None,
            flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT |
            gtk.WIN_POS_MOUSE,
            buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
        self.options = options
        self.set_default_size(350, 350)
        self.connect('response', self._response)
        self.notebook = gtk.Notebook()
        self.vbox.pack_start(self.notebook)

        buttons = SoundsFrame(self)
        self.notebook.append_page(buttons, gtk.Label(_('Audio')))

        self.notebook.show()
        self.show()

    def settings_changed(self):
        """Emit the settings changed message to parent."""
        self.emit('settings-changed')

    def _response(self, unused_dialog, response_id):
        """Wait for the close response."""
        if response_id == gtk.RESPONSE_CLOSE:
          LOG.info('Close in _Response.')
        self.destroy()

    @classmethod
    def register(cls):
        """Register this class as a Gtk widget."""
        gobject.type_register(SettingsDialog)


class CommonFrame(gtk.Frame):
    """Stuff common to several frames."""
    def __init__(self, settings):
        gtk.Frame.__init__(self)
        self.settings = settings
        self.create_layout()

    def create_layout(self):
        """Do nothing."""
        pass

    def _add_check(self, vbox, title, tooltip, option):
        """Add a check button."""
        check_button = gtk.CheckButton(label=title)
        val = getattr(self.settings.options, option)
        logging.info('got option %s as %s', option, val)
        if val:
            check_button.set_active(True)
        else:
            check_button.set_active(False)
        check_button.connect('toggled', self._toggled, option)
        check_button.set_tooltip_text(tooltip)
        vbox.pack_start(check_button, False, False)

    def _add_dropdown(self, vbox, title, tooltip, opt_lst, option, width_char=-1):
        """Add a drop down box."""
        hbox = gtk.HBox()
        label = gtk.Label(title)
        label.set_tooltip_text(tooltip)
        hbox.pack_start(label, expand=False, fill=False)

        combo = gtk.combo_box_entry_new_text()
        combo.child.set_width_chars(width_char)
        for opt in opt_lst:
            combo.append_text(str(opt))

        val = getattr(self.settings.options, option)
        if isinstance(val, float):
            str_val = '%0.3g' % val
        elif isinstance(val, int):
            str_val = '%d' % val
        else:
            str_val = val
        try:
            index = opt_lst.index(str_val)
        except ValueError:
            index = 0
        combo.set_active(index)

        combo.set_tooltip_text(tooltip)
        hbox.pack_start(combo, expand=False, fill=False, padding=10)
        logging.info('got option %s as %s', option, val)
        combo.connect('changed', self._combo_changed, option)

        vbox.pack_start(hbox, expand=False, fill=False)
        return combo

    def _toggled(self, widget, option):
        """The checkbox was toggled."""
        if widget.get_active():
          val = 1
        else:
          val = 0
        self._update_option(option, val, str(val))

    def _combo_changed(self, widget, option):
        """The combo box changed."""
        val = widget.get_active()
        str_val = widget.get_active_text()
        logging.info('str_val %s', str_val)
        self._update_option(option, val, str_val)

    def _update_option(self, option, unused_val, str_val):
        """Update an option."""
        setattr(self.settings.options, option, str_val)
        LOG.info('Set option %s to %s' % (option, str_val))
        self.settings.options.save()
        self.settings.settings_changed()


class SoundsFrame(CommonFrame):
    """The sound frame."""

    def __init__(self, settings):
      """Create common frame."""
      CommonFrame.__init__(self, settings)

    def create_layout(self):
      """Create the layout for buttons."""
      vbox = gtk.VBox()

      fnames = [x for x in os.listdir(os.path.abspath(os.path.dirname(__file__)))
              if x.endswith('.wav') or x.endswith('.ogg')]
      self._add_dropdown(
          vbox,
          _('Filename:'),
          _('When typing fast show more than one key typed.'),
          fnames, 'sound_file')

      self._add_dropdown(
          vbox,
          _('Volume:'),
          _('Percent volume to play the sound'),
          ['0', '10', '20', '30', '40', '50', '60', '70', '80', '90', '100'], 'volume')
      self.add(vbox)


def _test_settings_changed(unused_widget):
    """Help to test if the settings change message is received."""
    print 'Settings changed'


def manually_run_dialog():
    """Test the dialog without starting keymon."""
    import key_click

    keyclick = key_click.KeyClick()
    SettingsDialog.register()
    gettext.install('key_click', 'locale')
    logging.basicConfig(
        level=logging.DEBUG,
        format = '%(filename)s [%(lineno)d]: %(levelname)s %(message)s')
    keyclick.create_options()
    keyclick.opts.read_ini_file('~/.config/key-mon/config')
    dlg = SettingsDialog(None, keyclick.opts)
    dlg.connect('settings-changed', _test_settings_changed)
    dlg.show_all()
    dlg.run()
    return 0


if __name__ == '__main__':
    manually_run_dialog()
